package com.fwx.config;

import com.alibaba.fastjson.JSON;
import com.fwx.filter.LoginFilter;
import com.fwx.sercvice.MyUserDetailsService;
import com.fwx.util.JWTUtil;
import com.fwx.vo.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @program: springsecurity04
 * @description:
 * @author: 范文轩
 * @create: 2024-07-29 15:20
 **/

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private MyUserDetailsService userDetailsService;
    
    @Bean
    public PasswordEncoder passwordEncoder(){
        return  new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }
    
    @Autowired
    private LoginFilter loginFilter;
    
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        http.addFilterBefore(loginFilter, UsernamePasswordAuthenticationFilter.class);
        
        http.formLogin()
                .loginPage("/login.html")
                .loginProcessingUrl("/login")
                // .successForwardUrl("/success")
                .successHandler((httpServletRequest, httpServletResponse, authentication) -> {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter writer = httpServletResponse.getWriter();
                    
                    // 返回json对象
                    Map<String,Object> map=new HashMap<>();
                    map.put("username",authentication.getName());
                    Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
                    //获取权限
                    List<String> collect = authorities.stream().map(item -> item.getAuthority()).collect(Collectors.toList());

                    map.put("permissions",collect);
                    String token = JWTUtil.createToken(map);
                    redisTemplate.opsForValue().set("login:"+token,"");

                    //返回一个统一的json对象
                    R r=new R(200,"登录成功",token);
                    //转换为json字符串
                    String jsonString = JSON.toJSONString(r);
                    //servlet
                    writer.println(jsonString);
                    writer.flush();
                    writer.close();
                })
                
                // .failureForwardUrl("/fail")
                .failureHandler((httpServletRequest, httpServletResponse, e) -> {
                    httpServletResponse.setContentType("application/json;charset=utf-8");
                    PrintWriter writer = httpServletResponse.getWriter();
                    R r=new R(500,"登录失败",e.getMessage());
                    String jsonString = JSON.toJSONString(r);
                    writer.println(jsonString);
                    writer.flush();
                    writer.close();
                })
                .permitAll();
        
        // http.authorizeRequests().antMatchers("/fail.html").permitAll();
        
        // http.exceptionHandling().accessDeniedPage("/403.html");
        
        http.exceptionHandling().accessDeniedHandler((httpServletRequest, httpServletResponse, e) -> {
            httpServletResponse.setContentType("application/json;charset=utf-8");
            PrintWriter writer = httpServletResponse.getWriter();
            R r=new R(403,"权限不足",e.getMessage());
            String jsonString =JSON.toJSONString(r);
            writer.println(jsonString);
            writer.flush();
            writer.close();
        });

        //退出
        http.logout(item->{
            item.logoutSuccessHandler((httpServletRequest, httpServletResponse, e) -> {
                httpServletResponse.setContentType("application/json;charset=utf-8");
                PrintWriter writer = httpServletResponse.getWriter();
                String token = httpServletRequest.getHeader("token");
                redisTemplate.delete("login:"+token);
                R r=new R(200,"退出成功",null);
                String jsonString =JSON.toJSONString(r);
                writer.println(jsonString);
                writer.flush();
                writer.close();
            });
        });
        
        http.csrf().disable();
        
        http.cors(); // 登录允许跨域
        
        http.authorizeRequests().anyRequest().authenticated();
    }
}
